@@ -25,13 +25,15 @@ class Agent < ActiveRecord::Base |
||
| 25 | 25 |
|
| 26 | 26 |
EVENT_RETENTION_SCHEDULES = [["Forever", 0], ["1 day", 1], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n] })]
|
| 27 | 27 |
|
| 28 |
- attr_accessible :options, :memory, :name, :type, :schedule, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately |
|
| 28 |
+ attr_accessible :options, :memory, :name, :type, :schedule, :runner_ids, :target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately |
|
| 29 | 29 |
|
| 30 | 30 |
json_serialize :options, :memory |
| 31 | 31 |
|
| 32 | 32 |
validates_presence_of :name, :user |
| 33 | 33 |
validates_inclusion_of :keep_events_for, :in => EVENT_RETENTION_SCHEDULES.map(&:last) |
| 34 | 34 |
validate :sources_are_owned |
| 35 |
+ validate :runners_are_owned |
|
| 36 |
+ validate :targets_are_owned |
|
| 35 | 37 |
validate :scenarios_are_owned |
| 36 | 38 |
validate :validate_schedule |
| 37 | 39 |
validate :validate_options |
@@ -52,6 +54,10 @@ class Agent < ActiveRecord::Base |
||
| 52 | 54 |
has_many :links_as_receiver, :dependent => :delete_all, :foreign_key => "receiver_id", :class_name => "Link", :inverse_of => :receiver |
| 53 | 55 |
has_many :sources, :through => :links_as_receiver, :class_name => "Agent", :inverse_of => :receivers |
| 54 | 56 |
has_many :receivers, :through => :links_as_source, :class_name => "Agent", :inverse_of => :sources |
| 57 |
+ has_many :chains_as_runner, dependent: :delete_all, foreign_key: 'runner_id', class_name: 'Chain', inverse_of: :runner |
|
| 58 |
+ has_many :chains_as_target, dependent: :delete_all, foreign_key: 'target_id', class_name: 'Chain', inverse_of: :target |
|
| 59 |
+ has_many :runners, through: :chains_as_target, class_name: "Agent", inverse_of: :targets |
|
| 60 |
+ has_many :targets, through: :chains_as_runner, class_name: "Agent", inverse_of: :runners |
|
| 55 | 61 |
has_many :scenario_memberships, :dependent => :destroy, :inverse_of => :agent |
| 56 | 62 |
has_many :scenarios, :through => :scenario_memberships, :inverse_of => :agents |
| 57 | 63 |
|
@@ -218,6 +224,14 @@ class Agent < ActiveRecord::Base |
||
| 218 | 224 |
errors.add(:sources, "must be owned by you") unless sources.all? {|s| s.user == user }
|
| 219 | 225 |
end |
| 220 | 226 |
|
| 227 |
+ def runners_are_owned |
|
| 228 |
+ errors.add(:runners, "must be owned by you") unless runners.all? {|s| s.user == user }
|
|
| 229 |
+ end |
|
| 230 |
+ |
|
| 231 |
+ def targets_are_owned |
|
| 232 |
+ errors.add(:targets, "must be owned by you") unless targets.all? {|s| s.user == user }
|
|
| 233 |
+ end |
|
| 234 |
+ |
|
| 221 | 235 |
def scenarios_are_owned |
| 222 | 236 |
errors.add(:scenarios, "must be owned by you") unless scenarios.all? {|s| s.user == user }
|
| 223 | 237 |
end |
@@ -249,7 +263,7 @@ class Agent < ActiveRecord::Base |
||
| 249 | 263 |
|
| 250 | 264 |
class << self |
| 251 | 265 |
def build_clone(original) |
| 252 |
- new(original.slice(:type, :options, :schedule, :source_ids, :keep_events_for, :propagate_immediately)) { |clone|
|
|
| 266 |
+ new(original.slice(:type, :options, :schedule, :runner_ids, :source_ids, :keep_events_for, :propagate_immediately)) { |clone|
|
|
| 253 | 267 |
# Give it a unique name |
| 254 | 268 |
2.upto(count) do |i| |
| 255 | 269 |
name = '%s (%d)' % [original.name, i] |
@@ -399,6 +413,8 @@ class AgentDrop |
||
| 399 | 413 |
:sources, |
| 400 | 414 |
:receivers, |
| 401 | 415 |
:schedule, |
| 416 |
+ :runners, |
|
| 417 |
+ :targets, |
|
| 402 | 418 |
:disabled, |
| 403 | 419 |
:keep_events_for, |
| 404 | 420 |
:propagate_immediately, |
@@ -0,0 +1,7 @@ |
||
| 1 |
+# A Chain connects Agents in a run chain from the `runner` to the `target`. |
|
| 2 |
+class Chain < ActiveRecord::Base |
|
| 3 |
+ attr_accessible :runner_id, :target_id |
|
| 4 |
+ |
|
| 5 |
+ belongs_to :runner, class_name: 'Agent', inverse_of: :chains_as_runner |
|
| 6 |
+ belongs_to :target, class_name: 'Agent', inverse_of: :chains_as_target |
|
| 7 |
+end |
@@ -0,0 +1,13 @@ |
||
| 1 |
+class CreateChains < ActiveRecord::Migration |
|
| 2 |
+ def change |
|
| 3 |
+ create_table :chains do |t| |
|
| 4 |
+ t.integer :runner_id |
|
| 5 |
+ t.integer :target_id |
|
| 6 |
+ |
|
| 7 |
+ t.timestamps |
|
| 8 |
+ end |
|
| 9 |
+ |
|
| 10 |
+ add_index :chains, [:runner_id, :target_id], unique: true |
|
| 11 |
+ add_index :chains, :target_id |
|
| 12 |
+ end |
|
| 13 |
+end |
@@ -11,7 +11,7 @@ |
||
| 11 | 11 |
# |
| 12 | 12 |
# It's strongly recommended that you check this file into your version control system. |
| 13 | 13 |
|
| 14 |
-ActiveRecord::Schema.define(version: 20140605032822) do |
|
| 14 |
+ActiveRecord::Schema.define(version: 20140821155428) do |
|
| 15 | 15 |
|
| 16 | 16 |
create_table "agent_logs", force: true do |t| |
| 17 | 17 |
t.integer "agent_id", null: false |
@@ -50,6 +50,16 @@ ActiveRecord::Schema.define(version: 20140605032822) do |
||
| 50 | 50 |
add_index "agents", ["type"], name: "index_agents_on_type", using: :btree |
| 51 | 51 |
add_index "agents", ["user_id", "created_at"], name: "index_agents_on_user_id_and_created_at", using: :btree |
| 52 | 52 |
|
| 53 |
+ create_table "chains", force: true do |t| |
|
| 54 |
+ t.integer "runner_id" |
|
| 55 |
+ t.integer "target_id" |
|
| 56 |
+ t.datetime "created_at" |
|
| 57 |
+ t.datetime "updated_at" |
|
| 58 |
+ end |
|
| 59 |
+ |
|
| 60 |
+ add_index "chains", ["runner_id", "target_id"], name: "index_chains_on_runner_id_and_target_id", unique: true, using: :btree |
|
| 61 |
+ add_index "chains", ["target_id"], name: "index_chains_on_target_id", using: :btree |
|
| 62 |
+ |
|
| 53 | 63 |
create_table "delayed_jobs", force: true do |t| |
| 54 | 64 |
t.integer "priority", default: 0 |
| 55 | 65 |
t.integer "attempts", default: 0 |
@@ -486,7 +486,7 @@ describe Agent do |
||
| 486 | 486 |
agent.errors_on(:options).should include("cannot be set to an instance of Fixnum")
|
| 487 | 487 |
end |
| 488 | 488 |
|
| 489 |
- it "should not allow agents owned by other people" do |
|
| 489 |
+ it "should not allow source agents owned by other people" do |
|
| 490 | 490 |
agent = Agents::SomethingSource.new(:name => "something") |
| 491 | 491 |
agent.user = users(:bob) |
| 492 | 492 |
agent.source_ids = [agents(:bob_weather_agent).id] |
@@ -497,6 +497,28 @@ describe Agent do |
||
| 497 | 497 |
agent.should have(0).errors_on(:sources) |
| 498 | 498 |
end |
| 499 | 499 |
|
| 500 |
+ it "should not allow runner agents owned by other people" do |
|
| 501 |
+ agent = Agents::SomethingSource.new(:name => "something") |
|
| 502 |
+ agent.user = users(:bob) |
|
| 503 |
+ agent.runner_ids = [agents(:bob_weather_agent).id] |
|
| 504 |
+ agent.should have(0).errors_on(:runners) |
|
| 505 |
+ agent.runner_ids = [agents(:jane_weather_agent).id] |
|
| 506 |
+ agent.should have(1).errors_on(:runners) |
|
| 507 |
+ agent.user = users(:jane) |
|
| 508 |
+ agent.should have(0).errors_on(:runners) |
|
| 509 |
+ end |
|
| 510 |
+ |
|
| 511 |
+ it "should not allow target agents owned by other people" do |
|
| 512 |
+ agent = Agents::CannotBeScheduled.new(:name => "something") |
|
| 513 |
+ agent.user = users(:bob) |
|
| 514 |
+ agent.target_ids = [agents(:bob_weather_agent).id] |
|
| 515 |
+ agent.should have(0).errors_on(:targets) |
|
| 516 |
+ agent.target_ids = [agents(:jane_weather_agent).id] |
|
| 517 |
+ agent.should have(1).errors_on(:targets) |
|
| 518 |
+ agent.user = users(:jane) |
|
| 519 |
+ agent.should have(0).errors_on(:targets) |
|
| 520 |
+ end |
|
| 521 |
+ |
|
| 500 | 522 |
it "should not allow scenarios owned by other people" do |
| 501 | 523 |
agent = Agents::SomethingSource.new(:name => "something") |
| 502 | 524 |
agent.user = users(:bob) |